#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
#include "pcc32.h"

struct config {
  char editor[1024];
  char endpoint[1024];
  char send_group_id[12];
  int send_times;
  char send_keymap[10][1024];
};
static CURL *curl = NULL;
static struct curl_slist *headers = NULL;
static struct config config;

void init_config_defaults(struct config *config);
int read_config(char *filename, struct config *config);
void write_config(char *filename, struct config *config);
void print_config(struct config *confg);
void print_prompt();
void print_commands();
void init_curl();
void send_group_msg(char *send_group_id, int send_times, char* msg);
void show_status();
int http_post(char *path, char *data);

int main(int argc, char *argv[]) {
  system("chcp 65001");
  clearText();
  printf("v1.4\n");
  char *config_filename = argc > 1 ? argv[1] : "config.cfg";
  init_config_defaults(&config);
  int ret = read_config(config_filename, &config);
  if (ret == 1) {
    return ret;
  } else if (ret == 2) {
    write_config("config.cfg", &config);
  }

  init_curl();
  show_status();
  printf("按h输出帮助信息\n");

  while (1) {
    print_prompt();
    uint16 key;
    while(1) {
      key = jkGetKey();
      if (strchr("hq\x03rpcse0123456789", key)) {
        break;
      } else {
        putchar('\a');
      }
    }
    printf("%c\n", key);
    setTextColor(WHITE);
    if ('h' == key) {
      print_commands();
    } else if ('q' == key || 0x3 == key) {
      break;
    } else if ('r' == key) {
      printf("正在重载配置\n");
      int ret = read_config(config_filename, &config);
      if (ret == 0)
        printf("重载配置成功\n");
    } else if ('p' == key) {
      print_config(&config);
    } else if ('e' == key) {
      char cmd[256];
      sprintf(cmd, "%s %s", config.editor, config_filename);
      system(cmd);
      read_config(config_filename, &config);
    } else if ('c' == key) {
      clearText();
    } else if ('s' == key) {
      show_status();
    } else if (strchr("0123456789", key)) {
      char *msg = config.send_keymap[key - '0'];
      send_group_msg(config.send_group_id, config.send_times, msg);
    }
  }

  printf("退出\n");
  curl_global_cleanup();
  return 0;
}

void init_config_defaults(struct config *config) {
  strcpy(config->editor, "notepad");
  strcpy(config->endpoint, "http://localhost:3000");
  config->send_group_id[0] = '\0';
  config->send_times = 1;
  for (int i = 0; i < 10; i++) {
    sprintf(config->send_keymap[i], "%c", '0' + i);
  }
}

int read_config(char *filename, struct config *config) {
  FILE *fd = fopen(filename, "r");
  if (fd == NULL) {
    return 2;
  }

  while (1) {
    char c = getc(fd);
    if (c == EOF) {
      break;
    } else if (isspace(c)) {
      while (isspace(c)) c = getc(fd);
      ungetc(c, fd);
    } else if (c == '#') {
      while (c != '\n') c = getc(fd);
    } else {
      char item_key[20];
      char item_val[1024];
      char *pc;
      for (pc = item_key; c != '='; c = getc(fd)) *pc++ = c;
      *pc = '\0';
      c = getc(fd);
      for (pc = item_val; c != '\n'; c = getc(fd)) *pc++ = c;
      *pc = '\0';
      if (isdigit(item_key[0])) {
        uint16 k = item_key[0] - '0';
        strcpy(config->send_keymap[k], item_val);
      } else if (strcmp("group", item_key) == 0) {
        strcpy(config->send_group_id, item_val);
      } else if (strcmp("times", item_key) == 0) {
        config->send_times = atoi(item_val);
      } else if (strcmp("editor", item_key) == 0) {
        strcpy(config->editor, item_val);
      } else if (strcmp("endpoint", item_key) == 0) {
        strcpy(config->endpoint, item_val);
      }
    }
  }

  fclose(fd);
  return 0;

ERR:
  printf("配置有误\n");
  fclose(fd);
  return 1;
}

void write_config(char *filename, struct config *config) {
  FILE *fd = fopen(filename, "w");
  if (fd == NULL) {
    return;
  }

  fputs("# 配置默认编辑器\n", fd);
  fprintf(fd, "editor=%s\n\n", config->editor);
  fputs("# Napcat endpoint\n", fd);
  fprintf(fd, "endpoint=%s\n\n", config->endpoint);
  fputs("# 发送群消息的群号\n", fd);
  fprintf(fd, "group=%s\n\n", config->send_group_id);
  fputs("# 发送群消息的连续发送次数\n", fd);
  fprintf(fd, "times=%d\n\n", config->send_times);
  fputs("# 数字键发送的群消息文本\n", fd);
  for (int i = 0; i < 10; i++) {
    fprintf(fd, "%c=%s\n", i + 48, config->send_keymap[i]);
  }
  fclose(fd);
}

void print_config(struct config *config) {
  printf("Napcat endpoint: %s\n", config->endpoint);
  printf("配置默认编辑器: %s\n", config->editor);
  printf("发送群消息的群号: %s\n", config->send_group_id);
  printf("发送群消息的连续发送次数: %d\n", config->send_times);
  for (int i = 0; i < 10; i++) {
    printf("当按键%c发送消息 %s\n", i + 48, config->send_keymap[i]);
  }
}

void print_prompt() {
  setTextColor(LIGHT_GREEN);
  printf("❯ ");
  setTextColor(YELLOW);
}
void print_commands() {
  printf("h 帮助    q 退出    r 重载配置    p 查看配置    e 编辑配置    s 查看状态    c 清屏\n");
  printf("数字按键:\n");
  for (int i = 0; i < 10; i++) {
    printf("%c 发送群消息: %s\n", i + 48, config.send_keymap[i]);
  }
}

void init_curl() {
  curl_global_init(CURL_GLOBAL_DEFAULT);
  curl = curl_easy_init();
  if(curl == NULL) {
    printf("初始化失败");
    return;
  }
  headers = curl_slist_append(headers, "Content-Type: application/json");
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
  curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
  curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
  curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 30L);
  curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 15L);
}

int http_post(char *path, char *data) {
  char url[2048] = {0};
  strcat(url, config.endpoint);
  strcat(url, path);
  curl_easy_setopt(curl, CURLOPT_URL, url);
  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
  CURLcode res = curl_easy_perform(curl);
  if(res != CURLE_OK) {
    fprintf(stderr, "请求失败: %s\n", curl_easy_strerror(res));
    return 1;
  }
}

size_t print_response_write_cb(void *contents, size_t size, size_t nmemb, void *userp) {
  int textColor = getTextColor();
  if (strstr((char *)contents, "\"retcode\":0")) {
    setTextColor(GREEN);
    printf("成功\n");
  } else {
    setTextColor(RED);
    printf("失败:\n%s\n", contents);
  }
  setTextColor(textColor);
  return size * nmemb;
}

void send_group_msg(char *send_group_id, int send_times, char* msg) {
  char data[2048] = {0};
  sprintf(data, "{\"group_id\":%s,\"message\":[{\"type\":\"text\",\"data\":{\"text\":\"%s\"}}]}", send_group_id, msg);
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, print_response_write_cb);
  for (int t = 0; t < send_times; t++) {
    printf("正在发送群(群号=%s)消息: %s\n", send_group_id, msg);
    http_post("/send_group_msg", data);
  }
}

size_t print_bot_status_curl_write_cb(void *contents, size_t size, size_t nmemb, void *userp) {
  int textColor = getTextColor();
  if (strstr((char *)contents, "\"online\":true")) {
    setTextColor(GREEN);
    printf("正常\n");
  } else {
    setTextColor(RED);
    printf("异常\n");
  }
  setTextColor(textColor);
  return size * nmemb;
}

void show_status() {
  printf("正在查询状态\n");
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, print_bot_status_curl_write_cb);
  http_post("/get_status", "{}");
}

